
#include "stdafx.h"
#include "connector.h"
#include "ssession.h"

#include <vector>
#include <algorithm>

//////////////////////////////////////////////////////////////////////////
// ConnectBase
//////////////////////////////////////////////////////////////////////////
bool ConnectBase::Connect(std::string ip, int port)
{
	ZeroMemory( &m_sin, sizeof(SOCKADDR_IN) );

	m_sin.sin_family = AF_INET;
	m_sin.sin_port = ::htons( static_cast<u_short>(port));

	if(ip.empty())
	{
		m_sin.sin_addr.s_addr = ::htonl(INADDR_ANY);
	}
	else
	{
		unsigned long tmp = ::inet_addr(ip.c_str());
		memcpy( &m_sin.sin_addr.s_addr, &tmp, sizeof(unsigned long));
	}

	if( SOCKET_ERROR==::WSAConnect( m_socket, (SOCKADDR*)&m_sin, sizeof(m_sin), NULL, NULL, NULL, NULL) )
	{
		int err = ::WSAGetLastError();
		if(WSAEWOULDBLOCK!=err)
		{
			//TODO LOG
			return false;
		}
	}
	return true;
}

void ConnectBase::OnConnect(SOCKET s, bool result)
{
	if(m_pSession)
	{
		m_pSession->SetSocket(s);
		m_pSession->OnConnect(result);

		m_pSession->AssociateIOCPKey();
		m_pSession->PostRecv();
	}
}

//////////////////////////////////////////////////////////////////////////
// ConnectManager
//////////////////////////////////////////////////////////////////////////
void ConnectManager::Register(ConnectBase* pConnectBase)
{
	ConnectBase* pRegister = pConnectBase;
	HANDLE handle = ::WSACreateEvent();

	::WSAEventSelect( pRegister->GetSocket(), handle, FD_CONNECT);

	m_connectorVector.push_back(pRegister);
	m_handleVector.push_back(handle);
}

bool ConnectManager::ThreadConnect()
{
	if(!m_bRun) 
		return false;
	if(m_handleVector.empty())
		return true;

	int ret = ::WaitForMultipleObjects( (DWORD)m_handleVector.size(), &m_handleVector[0], false, 0);
	if( WAIT_FAILED== ret)
	{
	}
	else if(WAIT_TIMEOUT== ret)
	{
	}
	else
	{
		int index = ret-WAIT_OBJECT_0;
		WSANETWORKEVENTS networkEvent;
		int err = ::WSAEnumNetworkEvents( m_connectorVector[index]->GetSocket(), m_handleVector[index], &networkEvent);
		if(SOCKET_ERROR==err)
		{
			return true;
		}

		if(networkEvent.lNetworkEvents&FD_CONNECT)
		{
			bool result=false;
			if( 0==networkEvent.iErrorCode[FD_CONNECT_BIT] )
			{
				result=true;
			}

			m_connectorVector[index]->OnConnect( m_connectorVector[index]->GetSocket(), result );

			::WSACloseEvent( m_handleVector[index] );

			m_handleVector.erase( std::find(m_handleVector.begin(), m_handleVector.end(), m_handleVector[index]) );
			ConnectBase* pConnector = m_connectorVector[index];
			m_connectorVector.erase( std::find( m_connectorVector.begin(), m_connectorVector.end(), m_connectorVector[index]) );
			delete pConnector;
		}
	}
	return true;
}


